/************************************************************************************
**  
* @copyright (c) 2015-, Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file	    duye_cap_protocol.h
* @version     
* @brief      
* @author   
* @date     2013-01-21
* @note 
*
*  1. 2018-01-21 Created this file
* 
*/
#pragma once

#include <vector>
#include <string>
#include <duye_type.h>
#include <duye_singleton.h>

namespace duye {

/**
 * @brief protocol type
 */
typedef enum etag_ProtocolType {
	// link layer protocol
	PROTO_ETHER = 0,
	PROTO_IEEE,
	// network layer protocol
	PROTO_IP,
	PROTO_PPPOE,
	PROTO_ARP,
	PROTO_RARP,
	PROTO_8021Q,
	// transfer layer protocol
	PROTO_ICMP,
	PROTO_IGMP,
	PROTO_TCP,
	PROTO_UDP,
	// application layer protocol
	PROTO_HTTP,
	PROTO_HTTPS,
	PROTO_FTP,
	PROTO_TFTP,
	PROTO_SSH,
	PROTO_NUM,
	PROTO_NUKNOWN = PROTO_NUM
} ProtocolType;

/**
 * @brief protocol information
 */
class ProtoInfo {
public:
	ProtoInfo() : m_proto(PROTO_NUKNOWN), m_port(0) {}
	ProtoInfo(std::string name, ProtocolType type, uint16 port = 0)
		: m_proto(type)
		, m_name(name)
		, m_port(0) {}

	~ProtoInfo() {}

	void setProto(const ProtocolType proto) { m_proto = proto; }
	ProtocolType getProto() const { return m_proto; }

	void setName(const std::string& name) { m_name = name; }
	const std::string& getName() const { return m_name; }

	void setPort(const uint16 port) { m_port = port; }
	uint16 getPort() const { return m_port; }
	
private:
	ProtocolType m_proto;
	std::string m_name;
	uint16 m_port;
};

/**
 * @brief public protocol information class
 */
class Protocols : public Singleton<Protocols> {
public:
    typedef std::vector<ProtoInfo> ProtoInfoVector;
    
public:
    Protocols() {
		//m_protoInfoVector.push_back();
		m_protoInfoVector.push_back(ProtoInfo("ETHER", PROTO_ETHER, 0));
		m_protoInfoVector.push_back(ProtoInfo("IEEE", PROTO_IEEE, 0));
		m_protoInfoVector.push_back(ProtoInfo("IP", PROTO_IP, 0));
		m_protoInfoVector.push_back(ProtoInfo("PPPOE", PROTO_PPPOE, 0));
		m_protoInfoVector.push_back(ProtoInfo("ARP", PROTO_ARP, 0));
		m_protoInfoVector.push_back(ProtoInfo("RARP", PROTO_RARP, 0));
		m_protoInfoVector.push_back(ProtoInfo("8021Q", PROTO_8021Q, 0));
		m_protoInfoVector.push_back(ProtoInfo("ICMP", PROTO_ICMP, 0));
		m_protoInfoVector.push_back(ProtoInfo("IGMP", PROTO_IGMP, 0));
		m_protoInfoVector.push_back(ProtoInfo("TCP", PROTO_TCP, 0));
		m_protoInfoVector.push_back(ProtoInfo("UDP", PROTO_UDP, 0));
		m_protoInfoVector.push_back(ProtoInfo("HTTP", PROTO_HTTP, 80));
		m_protoInfoVector.push_back(ProtoInfo("HTTPS", PROTO_HTTPS, 443));
		m_protoInfoVector.push_back(ProtoInfo("FTP", PROTO_FTP, 23));
		m_protoInfoVector.push_back(ProtoInfo("TFTP", PROTO_TFTP, 0));
		m_protoInfoVector.push_back(ProtoInfo("SSH", PROTO_SSH, 22));
    }
    
    uint16 getPort(const ProtocolType& type) {
    	/*
        for (auto iter = m_protoInfoVector.begin(); iter != m_protoInfoVector.end(); ++iter)
        {
            if (iter->m_type == type)
            {
                return iter->m_port;
            }
        }
        */

        return 0;
    }

    std::string getName(const ProtocolType& type) {
    	ProtoInfoVector::iterator iter = m_protoInfoVector.begin();
        for (; iter != m_protoInfoVector.end(); ++iter) {
            if (iter->getProto() == type) {
                return iter->getName();
            }
        }

        return "unknown";
    }    

private:
    ProtoInfoVector m_protoInfoVector;
};

}
